package com.fox.webapp.web;

import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ValueConstants;

import com.fox.webapp.domain.LoginLog;
import com.fox.webapp.domain.Person;
import com.fox.webapp.service.IAccountService;
import com.fox.webapp.service.IAsyncActionService;
import com.fox.webapp.service.ILoginLogService;
import com.fox.webapp.service.IPersonService;
import com.fox.webapp.utils.Constant;
import com.fox.webapp.utils.ErrorCoding;
import com.fox.webapp.utils.WebUtil;
import com.springcryptoutils.core.digest.Digester;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	@Autowired
	private IPersonService personService;
	@Autowired
	private IAsyncActionService asyncActionService;
	@Autowired
	private IAccountService accountService;
	@Autowired
	private ILoginLogService loginLogService;
	@Autowired
	private Digester digester;
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model, HttpSession session) {
//		logger.info("Welcome home! The client locale is {}.", locale);
//		
//		Date date = new Date();
//		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
//		
//		String formattedDate = dateFormat.format(date);
//		
//		model.addAttribute("serverTime", formattedDate );
		
		if(session.getAttribute(Constant.SESSION_USER) != null){
			model.addAttribute("accountList", accountService.getMyAccounts((Person)session.getAttribute(Constant.SESSION_USER)));
		}
		
		return "home";
	}
	
	@RequestMapping(value = {"register", "register.html"}, method=RequestMethod.GET)
	public String regPage(HttpSession session){
		return "reg";
	}
	
	@RequestMapping(value = {"register", "register.html"}, method = RequestMethod.POST)
	public String register(Person p, Model model, HttpServletRequest request, HttpSession session, Locale locale, @CookieValue(required = false) String ref){
		Map<String, Integer> resultMap = new HashMap<String, Integer>();
		model.addAttribute("p", p);
		if (p == null) {
			model.addAttribute("errMsg", "no_variable");
			return "reg";
		}
		if (!StringUtils.hasText(p.getUsername())) {
			model.addAttribute("errMsg", "no_username");
			return "reg";
		}
		if (!StringUtils.hasText(p.getPassword())) {
			model.addAttribute("errMsg", "no_password");
			return "reg";
		}
		if (!p.getPassword().equals(p.getConfirmPassword())) {
			model.addAttribute("errMsg", "password_not_same");
			return "reg";
		}
		if(personService.isExist(p)){
			model.addAttribute("errMsg", "person_exist");
			return "reg";
		}
		if(ref != null && !ValueConstants.DEFAULT_NONE.equals(ref) && ObjectId.isValid(ref)) {
			p.setReferenceId(ref);
		}
		String ip = WebUtil.getIpAddr(request);
		p.setRegisterIp(ip);
		p.setRegisterTime(new Date());
		try{
			p.setPassword(digester.digest(p.getPassword()));
			p.setSecurityAnswer(p.getSecurityAnswer()==null?null:digester.digest(p.getSecurityAnswer()));
			p = personService.addNewPerson(p);
			resultMap.put(Constant.RESULT_STR, Constant.RESULT_SUCCESS);
			session.setAttribute(Constant.SESSION_USER, p);
			asyncActionService.sendWelcomeEmailAsync(p, locale);
			return "reg_success";
		} catch (Throwable t) {
			model.addAttribute("errMsg", "reg_failed");
			return "reg";
		}
	}
	
	@RequestMapping(value = {"login", "login.html"}, method = RequestMethod.GET)
	public String loginPage(HttpSession session, HttpServletRequest request, @CookieValue(value = Constant.COOKIE_USERNAME, defaultValue="") String username, @CookieValue(value = Constant.COOKIE_PASSWORD, defaultValue = "")String password){
		if(session.getAttribute(Constant.SESSION_USER) != null){
			return "redirect:i";
		}
		
		String thisIp = WebUtil.getIpAddr(request);
		
		if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
			Person p = personService.login(username, password, thisIp, true);
			if (p != null) {

				session.setAttribute(Constant.SESSION_USER, p);
				
				return "redirect:i";
			}
		}
		
		return "login";
	}
	
	@RequestMapping(value = {"logout", "logout.html"}, method = RequestMethod.GET)
	public String logoutPage(HttpSession session, HttpServletResponse response){
		session.setAttribute(Constant.SESSION_USER, null);
		Cookie c_rmu = new Cookie(Constant.COOKIE_USERNAME, null);
//		c_rmu.setDomain(Constant.COOKIE_DOMAIN);
		c_rmu.setMaxAge(0);
		c_rmu.setPath("/");
		Cookie c_rmp = new Cookie(Constant.COOKIE_PASSWORD, null);
//		c_rmp.setDomain(Constant.COOKIE_DOMAIN);
		c_rmp.setMaxAge(0);
		c_rmp.setPath("/");
		response.addCookie(c_rmu);
		response.addCookie(c_rmp);
		return "login";
	}
	
	@RequestMapping(value = {"login", "login.html"}, method = RequestMethod.POST)
	public String login(String mc_action, String username, String password, boolean rememberMe, HttpSession session, Model model, HttpServletRequest request, HttpServletResponse response){
		String thisIp = WebUtil.getIpAddr(request);
		int i = session.getAttribute(Constant.SESSION_LOGIN_FAILED_TIME) == null ? 1 : (Integer)session.getAttribute(Constant.SESSION_LOGIN_FAILED_TIME);
		i++;
		if(i > 3 && !StringUtils.hasText(mc_action)){
			password = "";
		}
		Person p = personService.login(username, digester.digest(password), thisIp, false);
		if (p != null) {
			session.setAttribute(Constant.SESSION_USER, p);
			
			String lastIp = p.getLastLoginIp();
			logger.debug(lastIp);
			
			p.setLastLoginIp(thisIp);
			personService.updatePersonLoginIp(p);
			
			if(!lastIp.equals(thisIp) && Math.random() > 0.9){//抽检ip问题
				asyncActionService.lookingForIp(p);
			}
			
			
			
			
			if (rememberMe) {
				Cookie c_rmu = new Cookie(Constant.COOKIE_USERNAME, p.getUsername());
//				c_rmu.setDomain(Constant.COOKIE_DOMAIN);
				c_rmu.setMaxAge(Constant.MONTH_SECONDS);
				c_rmu.setPath("/");
				Cookie c_rmp = new Cookie(Constant.COOKIE_PASSWORD, p.getPassword());
//				c_rmp.setDomain(Constant.COOKIE_DOMAIN);
				c_rmp.setMaxAge(Constant.MONTH_SECONDS);
				c_rmp.setPath("/");
				
				response.addCookie(c_rmu);
				response.addCookie(c_rmp);
			}
			return "redirect:i";
		} else {
			model.addAttribute("msg", "-1");
			session.setAttribute(Constant.SESSION_LOGIN_FAILED_TIME, i);
			return "login";
		}
	}
	
	@RequestMapping(value = {"forgetPassword", "forgetPassword.html"}, method = RequestMethod.GET)
	public String forgetPasswordPage(){
		return "getPassword";
	}
	
	@RequestMapping(value = "getMyPassword", method = RequestMethod.POST)
	public String doGetMyPassword(String username, String answer, Model model){
		if(!StringUtils.hasText(username) || !StringUtils.hasText(answer)){
			model.addAttribute("msg", 0);
			model.addAttribute("username", username);
			return forgetPasswordPage();
		}
		String uuid = personService.canResetMyPassword(username, digester.digest(answer));
		if(uuid != null){
			model.addAttribute("canReset", true);
			model.addAttribute("username", username);
			model.addAttribute("uuid", uuid);
			return "doResetPw";
		} else {
			model.addAttribute("msg", 0);
			model.addAttribute("username", username);
			return forgetPasswordPage();
		}
	}
	
	@RequestMapping(value = "emailMeToResetPassword", method = RequestMethod.POST)
	public String email2ResetPw(String username, Model model){
		Person p = personService.findPersonByUsername(username);
		model.addAttribute("username", username);
		if(p == null){
			model.addAttribute("msg", -1);
			return forgetPasswordPage();
		}
		if(p.getEmailVerified() == null || !p.getEmailVerified()){
			model.addAttribute("msg", -2);
			return forgetPasswordPage();
		}
		if(personService.sendResetPasswordEmail(p)){
			return "resetPwEmailed";
		}
		model.addAttribute("msg", 0);
		return forgetPasswordPage();
	}
	
	@RequestMapping(value = "getSecurityQuestion", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, String> getSecurityQuestion(String username){
		Map<String, String> map = new HashMap<String, String>();
		if(!StringUtils.hasText(username)){
			return map;
		}
		String sq = personService.getSecurityQuestion(username);
		map.put("result", sq);
		return map;
	}
	
	@RequestMapping(value = "resetPassword/{username}/resetUUid", method = RequestMethod.GET)
	public String resetPassword(@PathVariable String username, @PathVariable String resetUUid, Model model){
		if(personService.isPersonResetPasswordAvailable(username, resetUUid)){
			model.addAttribute("canReset", true);
			model.addAttribute("username", username);
			model.addAttribute("uuid", resetUUid);
		} else {
			model.addAttribute("canReset", false);
		}
		return "doResetPw";
	}
	
	@RequestMapping(value = "resetPassword", method = RequestMethod.POST)
	public String doResetPassword(String username, String uid, String password, String confirmPassword, Model model){
		if(personService.doResetPassword(username, uid, digester.digest(password))){
			return "resetPw_success";
		} else {
			model.addAttribute("msg", -1);
			return resetPassword(username, uid, model);
		}
	}
	
	@RequestMapping(value = {"emailVerify/{username}/{emailUUid}"}, method = {RequestMethod.GET})
	public String verifyEmail(@PathVariable String username, @PathVariable String emailUUid, Model model, HttpSession session){
		Person p = personService.verifyEmail(username, emailUUid);
		if(p != null){
//			session.setAttribute(Constant.SESSION_USER, p);
			model.addAttribute("verified", true);
		} else {
			model.addAttribute("verified", false);
		}
		return "emailVerified";
	}
	
	@RequestMapping(value = {"emailModify/{username}/{uuid}"}, method = {RequestMethod.GET})
	public String unVerifyEmail(@PathVariable String username, @PathVariable String uuid, Model model, HttpSession session){
		Person p = personService.unVerifyEmail(username, uuid);
		if(p != null){
			model.addAttribute("unverified", true);
		} else {
			model.addAttribute("unverified", false);
		}
		return "emailUnVerified";
	}
	
	@ExceptionHandler(RuntimeException.class)
	public String errorPage(RuntimeException re, Model model){
		logger.error(re.getLocalizedMessage());
		model.addAttribute("err", re.getLocalizedMessage());
		return "error";
	}
	
	@RequestMapping("404.html")
	public String page404(){
		return "404";
	}
}
